#==============================================================================
# Theta Scripting Engine - Action Cost Custom Battle System by privateer
#==============================================================================
# ► Version  : 1.0
#==============================================================================
# ► Introduction
# This script will enable you to use Action Cost Battle System as your battle 
# system. In simple terms, in an Action Cost Battle System, every actions like
# Attack, Item, Skill, or Defend, will cost a certain portion of an actor's 
# Action Point, or abbreviated AP. Think of AP as your actor's second SP pool,
# but it's more important, as even an action like Attack will use it. AP will
# regenerated each turn as the battle progresses.
# Also, a new command will be added to every actor's battle command. Its name
# can be changed in the Configuration and it will add an actor's AP by 1.
#==============================================================================
# ► Instruction
# ~ I purposedly created this battle system so it doesn't require flashy demo.
# Put this script above any other battle-related scripts you may use.
# If you use TSE-SkillCost, TSE-WeaponCost, and/or TSE-ItemCost, put this script 
# BELOW them.
#==============================================================================
# ► Compatibility
# Compliant with TSE-SkillCost, TSE-WeaponCost, TSE-ItemCost.
# Obviously incompatible with other Custom Battle System.
#==============================================================================
# ► Additional Informations
# To change a weapon's, a skill's , or an item's AP Cost, you can create an 
# element that goes like this : AP Cost : x, where as x is the amout of AP Cost
# you want, and put it in the respective object's element set. 
# Be mindful that these elements will stack. So, if there's a weapon with an 
# element like AP Cost : 5 and AP Cost : 2, its AP Cost will the total of those
# two. Or in this case, 7.
#==============================================================================
module TSE
  module ActionCostCBS
    # If true, all actors' AP start from 0.
    # I recommend to make END_WITH_O also true if you make this true.
    START_FROM_0 = true
    
    # If true, all actor's AP will be set to 0 when the battle end.
    END_WITH_0 = true
    
    # How much AP will be regenerated at one turn? 
    # I recommend it not to exceed 99, as AP is depleted in a smaller rate than 
    # SP.
    REGENERATED_AP = 1
    
    # Maximum AP an actor can have at one time. I recommend it not to exceed 99,
    # as AP is depleted in a smaller rate than SP.
    MAXIMUM_AP = 10
    
    # What is Action Point abbreviated?
    AP_WORD = "AP"
    
    # Color used to display an actor's current and maximum AP.
    AP_COLOR = Color.new(0, 255, 128, 255)
    
    # Do you want to display an actor's AP in battle?
    DISPLAY_IN_BATTLE = true
    
    # Command that increases an actor's AP by 1 point.
    CHARGE_COMMAND = "Reinforce"
    
    # Default AP Costs of actions in battle.
    ACTION_COSTS = { 
    # For attack
    "Attack" => 1,
    # For skills
    "Skill" => 1,
    # For items
    "Item" => 1,
    # For defend
    "Defend" => 1,
    }
  end
end

#==============================================================================
# DON'T EDIT ANY FURTHER UNLESS YOU KNOW WHAT YOU'RE DOING!
#==============================================================================

$imported = {} if $imported.nil?
$imported["TSE-ActionCostCBS"] = true

module TSE_Regex
  AP_COST = /(?:AP_COST|ap cost)[ ]:[ ](\d+)/i
end

#===============================================================================
# RPG Module
#===============================================================================
module RPG
  class Skill
    include TSE_Regex
    # ~ New Method : ap_cost
    def ap_cost
      n = 0
      self.element_set.each{|element|
      n += $1.to_i if AP_COST =~ $data_system.elements[element]}
      return n
    end
  end
  class Weapon
    include TSE_Regex
    # ~ New Method : ap_cost
    def ap_cost
      n = 0
      self.element_set.each{|element|
      n += $1.to_i if AP_COST =~ $data_system.elements[element]}
      return n
    end
  end
  class Item
    include TSE_Regex
    # ~ New Method : ap_cost
    def ap_cost
      n = 0
      self.element_set.each{|element|
      n += $1.to_i if AP_COST =~ $data_system.elements[element]}
      return n
    end
  end  
end

class Game_Actor < Game_Battler
  include TSE
  include ActionCostCBS
  attr_reader :ap
  
  alias tse_accbs_setup setup
  def setup(actor_id)
    tse_accbs_setup(actor_id) 
    @ap = 0
  end
  
  def ap=(ap)
    @ap = [[ap, maxap].min, 0].max
  end
  
  def maxap
    return MAXIMUM_AP
  end
  
  def get_attack_ap_cost
    n = ACTION_COSTS["Attack"]
    return [n, $data_weapons[self.weapon_id].ap_cost].max
  end
  
  def get_defend_ap_cost
    return ACTION_COSTS["Defend"]
  end
  
  def get_skill_ap_cost(skill)
    n = ACTION_COSTS["Skill"]
    return [n, skill.ap_cost].max
  end
  
  def get_item_ap_cost(item)
    n = ACTION_COSTS["Item"]
    return [n, item.ap_cost].max
  end  
  
  if $imported["TSE-WeaponCost"]
  alias tse_accbs_can_pay_weapon_cost? can_pay_weapon_cost?
  def can_pay_weapon_cost?
    n = tse_accbs_can_pay_weapon_cost?
    return n && self.ap >= get_attack_ap_cost
  end
  
  alias tse_accbs_pay_weapon_cost pay_weapon_cost 
  def pay_weapon_cost 
    tse_accbs_pay_weapon_cost
    self.ap -= get_attack_ap_cost
  end
  end
  
  alias tse_accbs_skill_can_use? skill_can_use?
  def skill_can_use?(skill_id)
    n = tse_accbs_skill_can_use?(skill_id)
    if $game_temp.in_battle
      return n && self.ap >= get_skill_ap_cost($data_skills[skill_id])
    else
      return n
    end
  end
  
  if $imported["TSE-SkillCost"]
  alias tse_accbs_pay_skill_cost pay_skill_cost
  def pay_skill_cost(skill)
    tse_accbs_pay_skill_cost(skill)
    if $game_temp.in_battle
      self.ap -= get_skill_ap_cost(skill)
    end
  end
  end

  if $imported["TSE-ItemCost"]
  alias tse_accbs_can_pay_item_cost? can_pay_item_cost?
  def can_pay_item_cost?(item)
    n = tse_accbs_can_pay_item_cost?(item)
    return n && self.ap >= get_item_ap_cost(item)
  end
  
  alias tse_accbs_pay_item_cost pay_item_cost
  def pay_item_cost(item)
    tse_accbs_pay_item_cost(item)
    self.ap -= get_item_ap_cost(item)
  end
  end

end

class Scene_Battle
  attr_reader :active_battler
  include TSE
  include ActionCostCBS
  
  def main
    if START_FROM_0
      for actor in $game_party.actors
        actor.ap = 0
      end
    end   
    # Initialize each kind of temporary battle data
    $game_temp.in_battle = true
    $game_temp.battle_turn = 0
    $game_temp.battle_event_flags.clear
    $game_temp.battle_abort = false
    $game_temp.battle_main_phase = false
    $game_temp.battleback_name = $game_map.battleback_name
    $game_temp.forcing_battler = nil
    # Initialize battle event interpreter
    $game_system.battle_interpreter.setup(nil, 0)
    # Prepare troop
    @troop_id = $game_temp.battle_troop_id
    $game_troop.setup(@troop_id)
    # Make actor command window
    s1 = $data_system.words.attack
    s2 = $data_system.words.skill
    s3 = $data_system.words.guard
    s4 = $data_system.words.item
    s5 = CHARGE_COMMAND
    @actor_command_window = Window_Command.new(160, [s1, s2, s3, s4, s5])
    @actor_command_window.y = 128
    @actor_command_window.back_opacity = 160
    @actor_command_window.active = false
    @actor_command_window.visible = false
    # Make other windows
    @party_command_window = Window_PartyCommand.new
    @help_window = Window_Help.new
    @help_window.back_opacity = 160
    @help_window.visible = false
    @status_window = Window_BattleStatus.new
    @message_window = Window_Message.new
    # Make sprite set
    @spriteset = Spriteset_Battle.new
    # Initialize wait count
    @wait_count = 0
    # Execute transition
    if $data_system.battle_transition == ""
      Graphics.transition(20)
    else
      Graphics.transition(40, "Graphics/Transitions/" +
        $data_system.battle_transition)
    end
   
    # Start pre-battle phase
    start_phase1
    # Main loop
    loop do
      # Update game screen
      Graphics.update
      # Update input information
      Input.update
      # Frame update
      update
      # Abort loop if screen is changed
      if $scene != self
        break
      end
    end
    # Refresh map
    $game_map.refresh
    # Prepare for transition
    Graphics.freeze
    # Dispose of windows
    @actor_command_window.dispose
    @party_command_window.dispose
    @help_window.dispose
    @status_window.dispose
    @message_window.dispose
    if @skill_window != nil
      @skill_window.dispose
    end
    if @item_window != nil
      @item_window.dispose
    end
    if @result_window != nil
      @result_window.dispose
    end
    # Dispose of sprite set
    @spriteset.dispose
    # If switching to title screen
    if $scene.is_a?(Scene_Title)
      # Fade out screen
      Graphics.transition
      Graphics.freeze
    end
    # If switching from battle test to any screen other than game over screen
    if $BTEST and not $scene.is_a?(Scene_Gameover)
      $scene = nil
    end
  end  
  def update_phase2
    # If C button was pressed
    if Input.trigger?(Input::C)
      # Branch by party command window cursor position
      case @party_command_window.index
      when 0  # fight
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        for actor in $game_party.actors
          actor.ap += REGENERATED_AP unless actor.dead?
        end
        @status_window.refresh
        # Start actor command phase
        start_phase3
      when 1  # escape
        # If it's not possible to escape
        if $game_temp.battle_can_escape == false
          # Play buzzer SE
          $game_system.se_play($data_system.buzzer_se)
          return
        end
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Escape processing
        update_phase2_escape
      end
      return
    end
  end  
  
  alias tse_accbs_update_phase3_basic_command update_phase3_basic_command
  def update_phase3_basic_command
    # If B button was pressed
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # Go to command input for previous actor
      phase3_prior_actor
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # Branch by actor command window cursor position
      case @actor_command_window.index
      when 0  # attack
        return tse_accbs_update_phase3_basic_command if $imported["TSE-WeaponCost"]
        if @active_battler.ap >= @active_battler.get_attack_ap_cost
          $game_system.se_play($data_system.decision_se)
          @active_battler.current_action.kind = 0
          @active_battler.current_action.basic = 0
          start_enemy_select
        else
          $game_system.se_play($data_system.buzzer_se)
          return
        end
      when 1  # skill
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Set action
        @active_battler.current_action.kind = 1
        # Start skill selection
        start_skill_select
      when 2  # guard
        if @active_battler.ap >= @active_battler.get_defend_ap_cost
          $game_system.se_play($data_system.decision_se)
          @active_battler.current_action.kind = 0
          @active_battler.current_action.basic = 1
          phase3_next_actor
        else
          $game_system.se_play($data_system.buzzer_se)
          return        
        end
      when 3  # item
        # Play decision SE
        $game_system.se_play($data_system.decision_se)
        # Set action
        @active_battler.current_action.kind = 2
        # Start item selection
        start_item_select
      when 4 # charge
        if @active_battler.ap < @active_battler.maxap
          $game_system.se_play($data_system.decision_se)
          @active_battler.current_action.kind = 3
          $game_system.se_play($data_system.battle_start_se)
          phase3_next_actor
        else
          $game_system.se_play($data_system.buzzer_se)
          return
        end
      end
      return
    end
  end
  
  alias tse_accbs_update_phase3_item_select update_phase3_item_select
  def update_phase3_item_select
    return tse_accbs_update_phase3_item_select if $imported["TSE-ItemCost"]
    # Make item window visible
    @item_window.visible = true
    # Update item window
    @item_window.update
    # If B button was pressed
    if Input.trigger?(Input::B)
      # Play cancel SE
      $game_system.se_play($data_system.cancel_se)
      # End item selection
      end_item_select
      return
    end
    # If C button was pressed
    if Input.trigger?(Input::C)
      # Get currently selected data on the item window
      @item = @item_window.item
      # If it can't be used
      unless $game_party.item_can_use?(@item.id)
        # Play buzzer SE
        $game_system.se_play($data_system.buzzer_se)
        return
      end
      unless @active_battler.ap >= @active_battler.get_item_ap_cost(@item)
        $game_system.se_play($data_system.buzzer_se)
        return        
      end
      # Play decision SE
      $game_system.se_play($data_system.decision_se)
      # Set action
      @active_battler.current_action.item_id = @item.id
      # Make item window invisible
      @item_window.visible = false
      # If effect scope is single enemy
      if @item.scope == 1
        # Start enemy selection
        start_enemy_select
      # If effect scope is single ally
      elsif @item.scope == 3 or @item.scope == 5
        # Start actor selection
        start_actor_select
      # If effect scope is not single
      else
        # End item selection
        end_item_select
        # Go to command input for next actor
        phase3_next_actor
      end
      return
    end
  end  
  
  def update_phase4_step2
    # If not a forcing action
    unless @active_battler.current_action.forcing
      # If restriction is [normal attack enemy] or [normal attack ally]
      if @active_battler.restriction == 2 or @active_battler.restriction == 3
        # Set attack as an action
        @active_battler.current_action.kind = 0
        @active_battler.current_action.basic = 0
      end
      # If restriction is [cannot perform action]
      if @active_battler.restriction == 4
        # Clear battler being forced into action
        $game_temp.forcing_battler = nil
        # Shift to step 1
        @phase4_step = 1
        return
      end
    end
    # Clear target battlers
    @target_battlers = []
    # Branch according to each action
    case @active_battler.current_action.kind
    when 0  # basic
      make_basic_action_result
    when 1  # skill
      make_skill_action_result
    when 2  # item
      make_item_action_result
    when 3
      make_charge_action_result
    end
    # Shift to step 3
    if @phase4_step == 2
      @phase4_step = 3
    end
  end
  alias tse_accbs_make_basic_action_result make_basic_action_result
  def make_basic_action_result
    if @active_battler.is_a?(Game_Actor)
      if @active_battler.current_action.basic == 0
        return tse_accbs_make_basic_action_result if $imported["TSE-WeaponCost"]
        @active_battler.ap -= @active_battler.get_attack_ap_cost
      elsif @active_battler.current_action.basic == 1
        @active_battler.ap -= @active_battler.get_defend_ap_cost
      end
    end
    tse_accbs_make_basic_action_result
  end
  
  def make_charge_action_result
    @help_window.set_text(CHARGE_COMMAND, 1)
    @active_battler.ap += 1
    return
  end
  
  alias tse_accbs_make_skill_action_result make_skill_action_result
  def make_skill_action_result
    tse_accbs_make_skill_action_result
    unless $imported["TSE-SkillCost"] || @active_battler.current_action.skill_id == 0
      skill = $data_skills[@active_battler.current_action.skill_id]
      @active_battler.ap -= @active_battler.get_skill_ap_cost(skill)
    end   
  end
  
  alias tse_accbs_make_item_action_result make_item_action_result
  def make_item_action_result
    unless $imported["TSE-ItemCost"] || @active_battler.current_action.item_id == 0
      if $game_party.item_can_use?(@active_battler.current_action.item_id)
        item = $data_items[@active_battler.current_action.item_id]
        @active_battler.ap -= @active_battler.get_item_ap_cost(item)
      end
    end  
    tse_accbs_make_item_action_result
  end
  
  alias tse_accbs_battle_end battle_end
  def battle_end(result)
    if END_WITH_0
      for actor in $game_party.actors
        actor.ap = 0
      end
    end
    tse_accbs_battle_end(result) 
  end
end
class Window_Base
  include TSE
  include ActionCostCBS
  def draw_actor_ap(actor, x, y, width = 144)
    self.contents.font.color = system_color
    self.contents.draw_text(x, y, 32, 32, AP_WORD)
    if width - 32 >= 108
      ap_x = x + width - 108
      flag = true
    elsif width - 32 >= 48
      ap_x = x + width - 48
      flag = false
    end
    self.contents.font.color = AP_COLOR
    self.contents.draw_text(ap_x, y, 48, 32, actor.ap.to_s, 2)
    # Draw MaxHP
    if flag
      self.contents.draw_text(ap_x + 48, y, 12, 32, "/", 1)
      self.contents.draw_text(ap_x + 60, y, 48, 32, actor.maxap.to_s)
    end
  end  
end
class Window_BattleStatus < Window_Base
  include TSE
  include ActionCostCBS
  alias tse_accbs_refresh refresh
  def refresh
    return tse_accbs_refresh unless DISPLAY_IN_BATTLE
    self.contents.clear
    @item_max = $game_party.actors.size
    for i in 0...$game_party.actors.size
      actor = $game_party.actors[i]
      actor_x = i * 160 + 4
      draw_actor_name(actor, actor_x, 0)
      draw_actor_hp(actor, actor_x, 20, 120)
      draw_actor_sp(actor, actor_x, 48, 120)
      draw_actor_ap(actor, actor_x, 76, 144)
      if @level_up_flags[i]
        self.contents.font.color = normal_color
        self.contents.draw_text(actor_x, 96, 120, 32, "LEVEL UP!")
      else
        draw_actor_state(actor, actor_x, 96)
      end
    end
  end
end
class Window_Item < Window_Selectable
  alias tse_accbs_draw_item draw_item
  def draw_item(index)
    return tse_accbs_draw_item(index) if $imported["TSE-ItemCost"]
    item = @data[index]
    case item
    when RPG::Item
      number = $game_party.item_number(item.id)
    when RPG::Weapon
      number = $game_party.weapon_number(item.id)
    when RPG::Armor
      number = $game_party.armor_number(item.id)
    end
    if item.is_a?(RPG::Item) && $game_party.item_can_use?(item.id)
      self.contents.font.color = normal_color
    else
      self.contents.font.color = disabled_color
    end
    if item.is_a?(RPG::Item) && $game_temp.in_battle 
      if $scene.active_battler.ap >= $scene.active_battler.get_item_ap_cost(item)
        self.contents.font.color = normal_color
      else
        self.contents.font.color = disabled_color
      end
    end
    x = 4 + index % 2 * (288 + 32)
    y = index / 2 * 32
    rect = Rect.new(x, y, self.width / @column_max - 32, 32)
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    bitmap = RPG::Cache.icon(item.icon_name)
    opacity = self.contents.font.color == normal_color ? 255 : 128
    self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
    self.contents.draw_text(x + 28, y, 212, 32, item.name, 0)
    self.contents.draw_text(x + 240, y, 16, 32, ":", 1)
    self.contents.draw_text(x + 256, y, 24, 32, number.to_s, 2)
  end  
end
